//
// Created by lz on 3/7/21.
//

#ifndef MYWEBLIB_NET_TCPCONNECTION_H_
#define MYWEBLIB_NET_TCPCONNECTION_H_

#include "base/noncopyable.h"
#include "base/StringPiece.h"
#include "base/Types.h"
#include "net/Callbacks.h"
#include "net/Buffer.h"
#include "net/InetAddress.h"

#include <memory>
#include <boost/any.hpp>    //any 可以存任何东西，提供一个返回当前持有的对象的类型的接口type()

struct tcp_info;

namespace lzweb
{
	namespace net
	{
		class Channel;
		class EventLoop;
		class Socket;

		///
		/// TCP connection, for both client and server usage.
		///
		/// This is an interface class, so don't expose too much details.
		class TcpConnection : noncopyable,
							  public std::enable_shared_from_this<TcpConnection>
		{
		 public:
			/// Constructs a TcpConnection with a connected sockfd
			///
			/// User should not create this object.

			TcpConnection(EventLoop* loop, const string& name,
				int sockfd, const InetAddress& localAddr,
				const InetAddress& peerAddr);
			~TcpConnection();

			EventLoop* getLoop() const
			{
				return loop_;
			}
			const string& name() const
			{
				return name_;
			}
			const InetAddress& localAddress() const
			{
				return localAddr_;
			}
			const InetAddress& peerAddress() const
			{
				return peerAddr_;
			}
			bool connected() const
			{
				return state_ == kConnected;
			}
			bool disconnected() const
			{
				return state_ == kDisconnected;
			}
			// return true if success.
			bool getTcpInfo(struct tcp_info*) const;
			string getTcpInfoString() const;

			// void send(string&& message); // C++11
			void send(const void* message, int len);
			void send(const StringPiece& message);
			// void send(Buffer&& message); // C++11
			void send(Buffer* message);  // this one will swap data
			void shutdown(); // NOT thread safe, no simultaneous calling
			// void shutdownAndForceCloseAfter(double seconds); // NOT thread safe, no simultaneous calling
			void forceClose();
			void forceCloseWithDelay(double seconds);
			void setTcpNoDelay(bool on);
			// reading or not
			void startRead();
			void stopRead();
			bool isReading() const
			{
				return reading_;
			}; // NOT thread safe, may race with start/stopReadInLoop

			void setContext(const boost::any& context)
			{
				context_ = context;
			}

			const boost::any& getContext() const
			{
				return context_;
			}

			boost::any* getMutableContext()
			{
				return &context_;
			}

			void setConnectionCallback(const ConnectionCallback& cb)
			{
				connectionCallback_ = cb;
			}

			void setMessageCallback(const MessageCallback& cb)
			{
				messageCallback_ = cb;
			}

			void setWriteCompleteCallback(const WriteCompleteCallback& cb)
			{
				writeCompleteCallback_ = cb;
			}

			void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
			{
				highWaterMarkCallback_ = cb;
				highWaterMark_ = highWaterMark;
			}

			/// Advanced interface

			Buffer* inputBuffer()
			{
				return &inputBuffer_;
			}

			Buffer* outputBuffer()
			{
				return &outputBuffer_;
			}

			/// Internal use only
			void setCloseCallback(const CloseCallback& cb)
			{
				closeCallback_ = cb;
			}

			// called when TcpServer accepts a new connection
			void connectEstablished();   // should be called only once
			// called when TcpServer has removed me from its map
			void connectDestroyed();  // should be called only once

		 private:

			enum StatE
			{
				kDisconnected, kConnecting, kConnected, kDisconnecting
			};

			//handle系列函数一般会被注册到Channel对象Callback成员中
			void handleRead(TimeStamp receiveTime);
			void handleWrite();
			void handleClose();
			void handleError();
			//void sendInLoop(string&& message);
			void sendInLoop(const StringPiece& message);
			void sendInLoop(const void* message, size_t len);
			void shutdownInLoop();
			// void shutdownAndForceCloseInLoop(double seconds);
			void forceCloseInLoop();
			void setState(StatE s)
			{
				state_ = s;
			}
			const char* stateToString() const;
			void startReadInLoop();
			void stopReadInLoop();

			EventLoop* loop_;
			const string name_;

			StatE state_;   // FIXME: use atomic variable
			bool reading_;  //标记TcpConnection的读状态？

			// we don't expose those classes to client.
			// socket_管理了对应的socket fd, 并且该socket fd的生命周期和TcpConnection相同
			std::unique_ptr<Socket> socket_;
			std::unique_ptr<Channel> channel_;
			const InetAddress localAddr_;
			const InetAddress peerAddr_;
			// 连接回调函数，默认的连接回调函数在Callbacks.h中声明，在TcpServer中实现，作用是打印连接的信息
			ConnectionCallback connectionCallback_;
			MessageCallback messageCallback_;
			WriteCompleteCallback writeCompleteCallback_;  //发送数据的缓冲区outputBuffer被清空，调用该函数
			HighWaterMarkCallback highWaterMarkCallback_;
			CloseCallback closeCallback_;
			size_t highWaterMark_;
			Buffer inputBuffer_;
			Buffer outputBuffer_;   // FIXME: use list<Buffer> as output buffer.

			boost::any context_;

			// FIXME: creationTime_, lastReceiveTime_
			//        bytesReceived_, bytesSent_


		};

		// has been declared in Callbacks.h , so could I comment it ?
		// using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
	} // namespace net
} // namespace lzweb



#endif //MYWEBLIB_NET_TCPCONNECTION_H_
